﻿/**
 * ChartGrid
 * Charts Collection
 *
 * @author		Duarte Peixinho
 * @version		1.0
 */

package com.duartepeixinho.charts.grid 
{
	import flash.display.Sprite;
	import flash.geom.Point;
	import flash.text.Font;
	import flash.text.TextField;
	import flash.text.TextFormat;
	
	public class ChartGrid extends Sprite
	{
		//constants
		private const LEFT_MARGIN:Number = 30;
		private const TOP_MARGIN:Number = 40;
		private const BOTTOM_MARGIN:Number = 30;
		
		//private vars
		private var _coordInit:Point;
		private var _coordEnd:Point;
		private var _xLabel:String;
		private var _yLabel:String;
		private var _xCount:Number;
		private var _yCount:Number;	
		private var _CountInit:Point;
		private var _CountEnd:Point;
		private var _showXMarks:Boolean;
		private var _showYMarks:Boolean;
		//counters
		private var _xSpace:Number;
		private var _ySpace:Number;
		
		private var _grid:Boolean;
		private var _showZero:Boolean;
		private var _title:String;

		/**
		 * Creates The Chart Grid.
		 *
		 * @param		coordEnd		Point		Point of the width and heigth if the axis
		 * @param		CountInit		Point		Point that determines the starting number of each axis
 		 * @param		CountEnd		Point		How many numbers in each axis
		 * @param		xCount			Number		Increase Number of the XX axis
		 * @param		yCount			Number		Increase Number of the YY axis
		 * @param		showXMarks		Boolean		Show Labels of the XX axis
		 * @param		showYMarks		Boolean		Show Labels of the YY axis
		 * @param		xLabel			String		String to appear as the label of the XX axis
		 * @param		yLabel			String		String to appear as the label of the YY axis
		 * @param		grid			Boolean		Show the background grid or not
		 * @param		showZero		Boolean		Show the 0 on the corner or not
		 * @param		title			String		Title of the chart
		 */
		
		public function ChartGrid(coordEnd:Point, CountInit:Point, CountEnd:Point, xCount:Number, yCount:Number, showXMarks:Boolean, showYMarks:Boolean, xLabel:String = null, yLabel:String = null, grid:Boolean = true, showZero:Boolean = true, title:String = null ) {

			this.graphics.drawRect(0, 0, coordEnd.x + 60, coordEnd.y + TOP_MARGIN + BOTTOM_MARGIN);
			
			_coordEnd = coordEnd;			
			_xLabel = xLabel;
			_yLabel = yLabel;
			_xCount = xCount;
			_yCount = yCount;
			_CountInit = CountInit;
			_CountEnd = CountEnd;
			_showXMarks = showXMarks;
			_showYMarks = showYMarks;
			_grid = grid;
			_showZero = showZero;
			_title = title;
			constructCoord();	
		}
		
		/*
		 * Draw the charts grid and axis
		 */ 
		private function constructCoord():void {
			/*
			 * label 0
			 */ 
			if (_showZero) {
				var labelPosition:Point = convertCoord(new Point(-8, 0));
				var label:TextField = new TextField();
				label.selectable = false;	
				label.x = labelPosition.x;
				label.y = labelPosition.y;			
				label.text = "0";	

				label.setTextFormat(new TextFormat(null, 8));
				label.height = label.textHeight+5;			
				addChild(label);
			}
			
			//sets the counter
			var i:Number;
			
			/*
			 *  xx coord			
			 */
			
			var xPoint:Point = convertCoord(new Point(0, 0));
			
			// Starts drawing
			graphics.lineStyle(1);			
			graphics.moveTo( xPoint.x, xPoint.y);				
			xPoint = convertCoord(new Point(_coordEnd.x + 15, 0));
			graphics.lineTo(xPoint.x, xPoint.y);	
			
			//calculating x size			
			_xSpace = (_coordEnd.x) / (_CountEnd.x);
			
			//xx marks
			if (_xCount > 0) {
				//setting the starting number of the label
				var labelX:Number = _CountInit.x;
				
				//loop to set the marks
				for (i = 0; i <= _coordEnd.x; i += _xSpace) {	
					//converting the point
					var pointX:Point = convertCoord(new Point(i, 0));
					//starting the drawing
					graphics.lineStyle(0x000000);
					graphics.moveTo(pointX.x, pointX.y - 2);
					graphics.lineTo(pointX.x, pointX.y + 3);
					
					//grid 
					if (_grid) {
						graphics.lineStyle(1,0x0000ff,0.1);
						graphics.moveTo(pointX.x, pointX.y - _coordEnd.y -10);
						graphics.lineTo(pointX.x, pointX.y + 3);
					}
					//show number labels
					if (i > 0 && _showXMarks) {
						//setting the texfield
						var labelBorderX:TextField = new TextField();
						labelBorderX.selectable = false;				
						labelBorderX.text = (Math.round(labelX * 100) / 100).toString();
						labelBorderX.setTextFormat(new TextFormat(null, 8));
						labelBorderX.x = pointX.x - labelBorderX.textWidth / 2-1;						
						labelBorderX.y = pointX.y +5;
						labelBorderX.height = labelBorderX.textHeight + 5;
						addChild(labelBorderX);
						labelX += _xCount;
					}	
				}
			}
			
			/*
			 * yy coord 
			 */
			
			var yPoint:Point = convertCoord(new Point(0, 0));
			
			// Starts Drawing
			graphics.lineStyle(1);
			graphics.moveTo(yPoint.x, yPoint.y);
			yPoint = convertCoord(new Point(0, _coordEnd.y + 10));
			graphics.lineTo(yPoint.x, yPoint.y);
			
			//calculating y size
			_ySpace = (_coordEnd.y) / (_CountEnd.y);
			
			//yy marks
			if (_yCount) {
				
				//setting the starting number of the label
				var labelY:Number = _CountInit.y;
				
				//loop to set the marks
				for (i = 0; i <= _coordEnd.y; i += _ySpace) {
					//converting the point
					var pointY:Point = convertCoord(new Point(0, i));
					//starting the drwaing
					graphics.lineStyle(0x000000);
					graphics.moveTo(pointY.x - 2, pointY.y);
					graphics.lineTo(pointY.x + 3, pointY.y);
										
					//grid 
					if (_grid) {
						graphics.lineStyle(1,0x0000ff,0.1);
						graphics.moveTo(pointY.x + _coordEnd.x +10, pointY.y);
						graphics.lineTo(pointY.x, pointY.y);
					}					
					//show number labels
					if (i > 0 && _showYMarks) {
						//setting the texfield
						var labelBorderY:TextField = new TextField();
						labelBorderY.text = (Math.round(labelY * 100) / 100).toString();
						labelBorderY.selectable = false;
						labelBorderY.setTextFormat(new TextFormat(null, 8));
						labelBorderY.y = pointY.y - labelBorderY.textHeight / 2 -2;
						labelBorderY.x = pointY.x -15 - labelBorderY.textWidth / 2;
						labelBorderY.height = labelBorderY.textHeight + 5;
						addChild(labelBorderY);
						labelY += _yCount;
					}	
				}
			}
			//creating axis arrows
			createArrows();		
			
			//setting title
			if (_title) {
				setTitle();
			}
		}
		
		/*
		 * 
		 */
		private function setTitle():void {
			var titleLabel:TextField = new TextField();
			titleLabel.text = _title;
			titleLabel.setTextFormat(new TextFormat(null, 14));
			titleLabel.height = titleLabel.textHeight + 5;
			titleLabel.width = titleLabel.textWidth + 5;

			titleLabel.x = convertCoord(new Point(_coordEnd.x / 2 - titleLabel.textWidth / 2, _coordEnd.y)).x;
			titleLabel.y = convertCoord(new Point(_coordEnd.x, _coordEnd.y)).y;
			addChild(titleLabel);
		}
		
		/*
		 * Creates the arrows of the axis
		 */
		private function createArrows():void {
			graphics.beginFill(0x000000);
			var point:Point = convertCoord(new Point(_coordEnd.x + 10 -3, -3));
			graphics.moveTo(point.x, point.y);
			point = convertCoord(new Point(_coordEnd.x + 15 + 3, 0));			
			graphics.lineTo(point.x, point.y);
			point = convertCoord(new Point(_coordEnd.x+10 - 3, 3));
			graphics.lineTo(point.x, point.y);
			if (_xLabel) {
				var xLabelText:TextField = new TextField();
				xLabelText.selectable = false;
				xLabelText.text = _xLabel;
				xLabelText.height = xLabelText.textHeight + 5;
				var labelPoint:Point = convertCoord(new Point(_coordEnd.x+20, 10));
				xLabelText.x = labelPoint.x;
				xLabelText.y = labelPoint.y;
				xLabelText.setTextFormat(new TextFormat(null, 11));
				addChild(xLabelText);
			}
			
			graphics.beginFill(0x000000);
			point = convertCoord(new Point(-3, _coordEnd.y+10 -3));
			graphics.moveTo(point.x, point.y);
			point = convertCoord(new Point(0, _coordEnd.y+15 + 3));
			graphics.lineTo(point.x, point.y);
			point = convertCoord(new Point(3, _coordEnd.y + 10 - 3));
			graphics.lineTo(point.x, point.y);
			if (_yLabel) {
				var yLabelText:TextField = new TextField();
				yLabelText.selectable = false;
				yLabelText.text = _yLabel;
				yLabelText.height = yLabelText.textHeight + 5;
				var labelPointY:Point = convertCoord(new Point(0 - yLabelText.textWidth/2, _coordEnd.y + 35));
				yLabelText.x = labelPointY.x;
				yLabelText.y = labelPointY.y;
				yLabelText.setTextFormat(new TextFormat(null, 11));
				addChild(yLabelText);
			}
		}
		/**
		 * Convertes a given point to the chart coordinates
		 *
		 * @param		num					Point		Point that is needed to be converted to the chart axis
		 * @return							Point		Converted Point
		 */
		private function convertCoord(num:Point):Point {
			num.x = num.x + LEFT_MARGIN;
			num.y = this.height - (num.y + BOTTOM_MARGIN);

			return num;
		}
		
		/**
		 * Convertes a given point to the chart coordinates scale
		 *
		 * @param		num					Point		Point to be converted to the chart axis scale
		 * @return							Point		Converted Point
		 */
		public function convertCoordChart(num:Point):Point {			
			//converting the x number to chart scale
			num.x = ((num.x / _xCount) * _xSpace) - (((_CountInit.x - _xCount) / _xCount) * _xSpace);
			//converting the y number to chart scale
			num.y = ((num.y / _yCount) * _ySpace) - (((_CountInit.y - _yCount) / _yCount) * _ySpace);
			//converting to the chart coordinates
			num = convertCoord(num);
			
			return num;
		}
	}
	
}